package com.cloudkinto.utils;

import com.cloudkinto.common.utils.barutil.JBarcode;
import com.cloudkinto.common.utils.barutil.JBarcodeFactory;
import com.cloudkinto.common.utils.barutil.encode.Code128Encoder;
import com.cloudkinto.common.utils.barutil.encode.InvalidAtributeException;
import com.cloudkinto.common.utils.barutil.paint.BaseLineTextPainter;
import com.cloudkinto.common.utils.barutil.paint.EAN8TextPainter;
import com.cloudkinto.common.utils.barutil.paint.WidthCodedPainter;
import com.cloudkinto.common.utils.barutil.util.ImageUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.krysalis.barcode4j.HumanReadablePlacement;
import org.krysalis.barcode4j.impl.codabar.CodabarBean;
import org.krysalis.barcode4j.impl.code128.Code128Bean;
import org.krysalis.barcode4j.impl.code39.Code39Bean;
import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider;
import org.krysalis.barcode4j.tools.UnitConv;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Author Administrator
 *
 * @Des
 * @Version
 * @Date 2021/1/5
 */
public class BarCodeUtils {

    //设置条形码高度
    private static final int BARCODE_HEIGHT = 40;
    //设置条形码默认分辨率
    private static final int BARCODE_DPI = ImageUtil.DEFAULT_DPI;
    //设置条形码字体样式
    private static final String FONT_FAMILY = "console";
    //设置条形码字体大小
    private static final int FONT_SIZE = 15;
    //设置条形码文本
    public static String TEXT = "";
    //创建jbarcode
    private static JBarcode jbc = null;

    public static BarCodeUtils getJBarcode() throws InvalidAtributeException {
        /**
         * 参考设置样式：
         *barcode.setEncoder(Code128Encoder.getInstance()); //设置编码
         *barcode.setPainter(WidthCodedPainter.getInstance());// 设置Painter
         *barcode.setTextPainter(BaseLineTextPainter.getInstance()); //设置TextPainter
         *barcode.setBarHeight(17); //设置高度
         *barcode.setWideRatio(Double.valueOf(30).doubleValue());// 设置宽度比率
         *barcode.setXDimension(Double.valueOf(2).doubleValue()); // 设置尺寸，大小 密集程度
         *barcode.setShowText(true); //是否显示文本
         *barcode.setCheckDigit(true); //是否检查数字
         *barcode.setShowCheckDigit(false); //是否显示检查数字
         */
        if (jbc == null) {
            //生成code128
            jbc = JBarcodeFactory.getInstance().createCode128();
            jbc.setEncoder(Code128Encoder.getInstance());
//            jbc.setTextPainter(CustomTextPainter.getInstance());
            jbc.setBarHeight(BARCODE_HEIGHT);
            jbc.setXDimension(Double.valueOf(0.8).doubleValue());
            jbc.setShowText(true);
        }
        return new BarCodeUtils();
    }

    public static String createCodeImage(String str, String path, String fileName) {
        try {
            JBarcode localJBarcode = new JBarcode(Code128Encoder.getInstance(), WidthCodedPainter.getInstance(), BaseLineTextPainter.getInstance());
            localJBarcode.setXDimension(0.6d);
            BufferedImage localBufferedImage = localJBarcode.createBarcode(str);
            return saveToJPEG(localBufferedImage, path, fileName);
        } catch (Exception localException) {
            localException.printStackTrace();
            return null;
        }
    }

    public static byte[] createCodeImage(String str) {
        try {
            JBarcode localJBarcode = new JBarcode(Code128Encoder.getInstance(), WidthCodedPainter.getInstance(), EAN8TextPainter.getInstance());
            BufferedImage localBufferedImage = localJBarcode.createBarcode(str);

            return localBufferedImage.toString().getBytes();
        } catch (Exception localException) {
            localException.printStackTrace();
            return null;
        }
    }

    /**
     * 生成code39条形码
     *
     * @param msg 条形码内容
     * @return byte[]
     */
    public static byte[] generateBarCode39(String msg) {
        if (StringUtils.isEmpty(msg)) {
            return null;
        }
        Code39Bean bean = new Code39Bean();
        // 精细度
        final int dpi = 256;
        // module宽度
        final double moduleWidth = UnitConv.in2mm(5.0f / dpi);
        // 配置对象
        bean.setModuleWidth(moduleWidth);
        bean.setWideFactor(3);

        // 设置条码每一条的宽度
        // UnitConv 是barcode4j 提供的单位转换的实体类，用于毫米mm,像素px,英寸in,点pt之间的转换
        // 设置条形码高度和宽度
        bean.setBarHeight(ObjectUtils.defaultIfNull(10.00, 9.0D));

        // 设置两侧是否加空白
        bean.doQuietZone(false);

        bean.setMsgPosition(HumanReadablePlacement.HRP_NONE);

        String format = "image/png";
        ByteArrayOutputStream ous = null;
        byte[] imageByte;
        try {
            ous = new ByteArrayOutputStream();
            // 输出到流
            BitmapCanvasProvider canvas = new BitmapCanvasProvider(ous, format, dpi,
                    BufferedImage.TYPE_BYTE_BINARY, false, 0);
            // 生成条形码
            bean.generateBarcode(canvas, msg);
            // 结束绘制
            canvas.finish();
            imageByte = ous.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (null != ous) {
                    ous.close();
                }
            } catch (Exception e) {
//                log.error("ByteArrayOutputStream流关闭失败，失败原因为：{{}}", e.getMessage());
            }
        }
        return imageByte;
    }

    /**
     * 生成条形码 类型：code128
     *
     * @param code              要生成条形码的内容
     * @param isHideText        是否隐藏文本
     * @param isQuietZone       是否留白
     * @param dpi               分辨率：值越大条码越长，分辨率越高
     * @param height            条形码高度
     * @param width             条码宽度
     * @param quietZone         两侧留白 单位：mm
     * @param quietZoneVertical 上下留白 单位：mm
     */
    public static byte[] generateBarCodeNw7(
            String code,
            boolean isHideText,
            boolean isQuietZone,
            int dpi,
            double height,
            float width,
            double quietZone,
            double quietZoneVertical) {
        if (StringUtils.isEmpty(code)) {
            return null;
        }
        // 如果想要其他类型的条码(CODE 39, EAN-8...)直接获取相关对象Code39Bean...等等
        CodabarBean bean = new CodabarBean();
        // UnitConv 是barcode4j 提供的单位转换的实体类，用于毫米mm,像素px,英寸in,点pt之间的转换 UnitConv.in2mm(5.0f / dpi)
        bean.setBarHeight(ObjectUtils.defaultIfNull(height, 9.0D));
        bean.setModuleWidth(width);
        // 设置文本位置（包括是否显示）
        if (isHideText) {
            bean.setMsgPosition(HumanReadablePlacement.HRP_NONE);
        } else {
            bean.setDisplayStartStop(true);
            bean.setFontSize(UnitConv.pt2mm(18.0));
//            bean.setFontName();
            bean.setMsgPosition(HumanReadablePlacement.HRP_BOTTOM);
        }
        // 设置两侧是否留白
        if (isQuietZone) {
            bean.doQuietZone(true);
            //设置两侧留白宽度
            bean.setQuietZone(quietZone);
            //设置上下留白高度
            bean.setVerticalQuietZone(quietZoneVertical);
        }
        // 设置图片类型
        String format = "image/png";
        ByteArrayOutputStream ous = null;
        byte[] imageByte = null;
        try {
            ous = new ByteArrayOutputStream();
            BitmapCanvasProvider canvas = new BitmapCanvasProvider(
                    ous,
                    format,
                    dpi,
                    BufferedImage.TYPE_BYTE_BINARY,
                    false,
                    0
            );
            // 生产条形码
            bean.generateBarcode(canvas, code);
            // 结束
            canvas.finish();
            imageByte = ous.toByteArray();
        } catch (IOException e) {
//            log.error("IOException:" + e.getMessage());
        } finally {
            try {
                if (null != ous) {
                    ous.close();
                }
            } catch (Exception e) {
//                log.error("ByteArrayOutputStream流关闭失败，失败原因为：{{}}", e.getMessage());
            }
        }
        return imageByte;
    }

    public static byte[] generateBarCode128(
            String code,
            boolean isHideText,
            boolean isQuietZone,
            int dpi,
            double height,
            float width,
            double quietZone,
            double quietZoneVertical) {
        if (StringUtils.isEmpty(code)) {
            return null;
        }
        // 如果想要其他类型的条码(CODE 39, EAN-8...)直接获取相关对象Code39Bean...等等
        Code128Bean bean = new Code128Bean();
        // UnitConv 是barcode4j 提供的单位转换的实体类，用于毫米mm,像素px,英寸in,点pt之间的转换 UnitConv.in2mm(5.0f / dpi)
        bean.setBarHeight(ObjectUtils.defaultIfNull(height, 9.0D));
        bean.setModuleWidth(width);
        // 设置文本位置（包括是否显示）
        if (isHideText) {
            bean.setMsgPosition(HumanReadablePlacement.HRP_NONE);
        } else {
            bean.setFontSize(UnitConv.pt2mm(10.0));
//            bean.setFontName();
            bean.setMsgPosition(HumanReadablePlacement.HRP_BOTTOM);
        }
        // 设置两侧是否留白
        if (isQuietZone) {
            bean.doQuietZone(true);
            //设置两侧留白宽度
            bean.setQuietZone(quietZone);
            //设置上下留白高度
            bean.setVerticalQuietZone(quietZoneVertical);
        }
        // 设置图片类型
        String format = "image/png";
        ByteArrayOutputStream ous = null;
        byte[] imageByte = null;
        try {
            ous = new ByteArrayOutputStream();
            BitmapCanvasProvider canvas = new BitmapCanvasProvider(
                    ous,
                    format,
                    dpi,
                    BufferedImage.TYPE_BYTE_BINARY,
                    false,
                    0
            );
            // 生产条形码
            bean.generateBarcode(canvas, code);
            // 结束
            canvas.finish();
            imageByte = ous.toByteArray();
        } catch (IOException e) {
//            log.error("IOException:" + e.getMessage());
        } finally {
            try {
                if (null != ous) {
                    ous.close();
                }
            } catch (Exception e) {
//                log.error("ByteArrayOutputStream流关闭失败，失败原因为：{{}}", e.getMessage());
            }
        }
        return imageByte;
    }

    static String saveToJPEG(BufferedImage paramBufferedImage, String path, String fileName) {
        return saveToFile(paramBufferedImage, path, fileName);

    }

    static String saveToFile(BufferedImage paramBufferedImage, String path, String fileName) {
        String uri = path + File.separator + fileName;
        try {
            FileOutputStream localFileOutputStream = new FileOutputStream(uri);
            ImageUtil.encodeAndWrite(paramBufferedImage, "png", localFileOutputStream, 350, 150);
            localFileOutputStream.close();
            return uri;
        } catch (Exception localException) {
            localException.printStackTrace();
            return null;
        }
    }

}
